using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using WP.Commons;

using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Data;
using System.IO;



namespace WP.Modules
{
    public partial class frmPrintView : Form
    {
        public delegate LocalReport OnGetLocalReport(ReportDataSource reportDataSource,  string strRptName, ReportParameter[] rptParaArray);
        public event OnGetLocalReport GetLocalReport;

        public delegate ReportViewer OnGetReportViewer(ReportDataSource reportDataSource, string strRptName, ReportParameter[] rptParaArray);
        public event OnGetReportViewer GetReportViewer;

        public delegate byte[] OnGetReportString(string strRptName);
        public event OnGetReportString GetReportString;

        private ReportDataSource reportDataSource;
        private BindingSource dataTableBindingSource;
        private PrintInfo m_printInfo;
        private bool mblnAlreadyRefresh = false;
        private bool mblnAlreadyError = false;
        public bool mblnShowDialog = false;
        public bool UseShowDialog
        {
            get
            {
                return mblnShowDialog;
            }
            set
            {
                mblnShowDialog = value;
            }
        }

        private ReportViewer m_view=null;
        public frmPrintView()
        {
            InitializeComponent();
            this.components = new System.ComponentModel.Container();
            reportDataSource = new Microsoft.Reporting.WinForms.ReportDataSource();
            dataTableBindingSource = new BindingSource(this.components);

            
        }

        

        public void OutPutReport(PrintInfo printInfo, string strRptDataSourceName, string strRptName, DataSet dt, ReportParameter[] rptParaArray)
        {

            m_printInfo = printInfo;
            reportDataSource.Name = strRptDataSourceName;
            reportDataSource.Value = dataTableBindingSource;
            dataTableBindingSource.DataMember = dt.Tables[0].ToString();
            dataTableBindingSource.DataSource = dt;

            OutPut(strRptDataSourceName, strRptName, rptParaArray);
            ReleaseOldStream();
            if (m_Files != null)
            {
                foreach (string strFile in m_Files)
                {
                    try
                    {
                        System.IO.File.Delete(strFile);
                    }
                    catch
                    {
                    }
                }
                m_Files = null;
            }
        }

        private void ReleaseOldStream()
        {
            if (m_OldStream != null)
            {
                m_OldStream.Flush();
                m_OldStream.Close();
                m_OldStream.Dispose();
                m_OldStream = null;
            }
        }

        private void frmPrintView_Load(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Maximized;

        }

        private void OutPut(string strRptDataSourceName, string strRptName, ReportParameter[] rptParaArray)
        {
            LocalReport report = GetLocalReport(reportDataSource, strRptName, rptParaArray);
            if (m_printInfo.PrintType == PrintInfo.OutputType.Preview)
            {
                if (m_view == null)
                {
                    m_view = GetReportViewer(reportDataSource, strRptName, rptParaArray);                    
                }
                this.Text = m_printInfo.ReportTitle;
                                
                m_view.SetDisplayMode(DisplayMode.PrintLayout);
                if (Customize.UsePerDisplayWhenPrintView())
                {
                    m_view.ZoomMode = ZoomMode.Percent;
                    m_view.ZoomPercent = 100;
                }
                m_view.RefreshReport();
                
                //      this.MdiParent = SysVar.MDIParentForm;
                if (this.UseShowDialog)
                {
                    System.Threading.Thread.Sleep(1000);
                    this.ShowDialog();
                }
                else
                {
                    this.Show();
                }
                if (m_printInfo.ReportExportFileName.Trim() != "")
                {
                    if (m_printInfo.ReportExportType == PrintInfo.ExportType.PDF)
                        m_printInfo.PrintType = PrintInfo.OutputType.PDF;
                    else
                        m_printInfo.PrintType = PrintInfo.OutputType.Excel;

                    Export(report,strRptName );
                }
            }
            else
            {

                Export(report, strRptName);
                if (m_printInfo.PrintType == PrintInfo.OutputType.Print || m_printInfo.PrintType == PrintInfo.OutputType.Email || m_printInfo.PrintType == PrintInfo.OutputType.Fax)
                {
                    m_currentPageIndex = 0;
                    Print();
                    if (m_printInfo.ReportExportFileName.Trim() != "")
                    {
                        if (m_printInfo.ReportExportType == PrintInfo.ExportType.PDF)
                            m_printInfo.PrintType = PrintInfo.OutputType.PDF;
                        else
                            m_printInfo.PrintType = PrintInfo.OutputType.Excel;
                        Export(report, strRptName);
                    }
                }

            }
        }
        private int m_currentPageIndex;
        //private IList<Stream> m_streams;
        private IList<string> m_Files;
        private Stream m_OldStream = null;
        private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
        {


            if (m_printInfo.PrintType != PrintInfo.OutputType.Print && m_printInfo.PrintType != PrintInfo.OutputType.Fax && m_printInfo.PrintType != PrintInfo.OutputType.Email)
            {
                if (m_printInfo.ReportExportType == PrintInfo.ExportType.PDF)
                    fileNameExtension = "PDF";
                else
                    fileNameExtension = "xls";

                ReleaseOldStream();
                string strFile = m_printInfo.ReportExportFileName + "." + fileNameExtension;
                System.IO.Stream stream = new FileStream(strFile, FileMode.Create);
                m_OldStream = stream;

                
                return stream;
            }
            else
            {
                ReleaseOldStream();
                string strFile = System.IO.Path.GetTempFileName();
                System.IO.Stream stream = new FileStream(strFile, FileMode.Create);
                m_OldStream = stream;

                m_Files.Add(strFile);
                return stream;
            }
        }
        private void Export(LocalReport report, string strRptName)
        {
            try
            {
                string strFormat = "Image";
                Warning[] warnings;
                m_Files = new List<string>();
                switch (m_printInfo.PrintType)
                {
                    case PrintInfo.OutputType.Email:
                    case PrintInfo.OutputType.Fax:
                    case PrintInfo.OutputType.Print:
                        strFormat = "Image";
                        break;
                    case PrintInfo.OutputType.PDF:
                    case PrintInfo.OutputType.Nothing:
                        strFormat = "PDF";
                        break;
                    case PrintInfo.OutputType.Excel:
                        strFormat = "Excel";
                        break;
                }

                report.Render(strFormat, Export_GetDeviceInfoString(m_printInfo, strRptName), CreateStream, out warnings);

                ////if (m_printInfo.PrintType == PrintInfo.OutputType.Print)
                ////{
                //foreach (Stream stream in m_streams)
                //    stream.Position = 0;
                ////}
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        private string Export_GetDeviceInfoString(PrintInfo printInfo, string strRptName)
        {
            if ( GetReportString != null)
            {
                try
                {
                    byte[] buffer = GetReportString(strRptName);
                    string strRpt = Encoding.UTF8.GetString(buffer);
                    if (strRpt.Length > 0)
                    {
                            printInfo.MarginLeft = GetMargin(strRpt, "LeftMargin");
                            printInfo.MarginRight = GetMargin(strRpt, "RightMargin");
                            printInfo.MarginTop = GetMargin(strRpt, "TopMargin");
                            printInfo.MarginBottom = GetMargin(strRpt, "BottomMargin");

                    }

                    return printInfo.DeviceInfoString;
                }
                catch
                {
                    return printInfo.DeviceInfoString;
                }
            }
            else
            {
                return printInfo.DeviceInfoString;
            }
        }
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            ReleaseOldStream();
            Metafile pageImage = new Metafile(new FileStream(m_Files[m_currentPageIndex], FileMode.Open));
            
            ev.Graphics.DrawImage(pageImage,GetPageBounds( ev));

            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_Files.Count);
        }

        private Rectangle GetPageBounds(PrintPageEventArgs ev)
        {
            if (GetReportString != null)
            {
                Rectangle destRect ;
                try
                {
                    destRect = new Rectangle(ev.PageBounds.Left - ((int)ev.PageSettings.HardMarginX), ev.PageBounds.Top - ((int)ev.PageSettings.HardMarginY), ev.PageBounds.Width, ev.PageBounds.Height);

                }
                catch
                {
                    destRect = ev.PageBounds;
                }
                    return destRect;
            }
            else
            {
                return ev.PageBounds;
            }
        }

        private void Print()
        {

            if (m_Files == null || m_Files.Count == 0)
                return;

            PrintDocument printDoc = new PrintDocument();
            printDoc.PrinterSettings.PrinterName = m_printInfo.PrinterName;
            printDoc.PrinterSettings.Copies = m_printInfo.PrinterSetting.Copies ;
            
            printDoc.DefaultPageSettings.Landscape = m_printInfo.Landscape;
            printDoc.DocumentName = m_printInfo.FaxEmailInfo; // "@F201 JEREMY PENNER@@F211 (214)521-4616@@F110 (604) 244-7966@@F101 WOODPRO Lumber Co@@F307 asedfwerwerwer@";

            if (!printDoc.PrinterSettings.IsValid)
            {
                string msg = String.Format("Can't find printer \"{0}\".", m_printInfo.PrinterName);
                MessageBox.Show(Msg.Select(msg, DataFunctions.GetMsg(this.Name, "MSG_CanNotFindPrinter", new string[] { m_printInfo.PrinterName })), SysVar.ErrTitle);
                return;
            }
            printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            printDoc.Print();
        }

        private void rptView_RenderingComplete(object sender, RenderingCompleteEventArgs e)
        {
            //Console.WriteLine(string.Format("{0}:{1}", DateTime.Now, "rptView_RenderingComplete"));
            if (e.Exception != null)
            {
                Console.WriteLine(string.Format("{0}:{1}", DateTime.Now, e.Exception.Message));
            }

            if (!mblnAlreadyRefresh && (e.Exception != null))
            {

                mblnAlreadyRefresh = true;

                //System.Threading.Thread.Sleep(3000);
                Application.DoEvents();

                ((ReportViewer)sender).RefreshReport();
                
            }
        }

        private void rptView_ReportError(object sender, ReportErrorEventArgs e)
        {
            if (e.Exception != null)
            {
                Console.WriteLine(string.Format("{0}:{1}", DateTime.Now, e.Exception.Message));
            }
            if (!mblnAlreadyError && e.Exception != null)
            {
                mblnAlreadyError = true;

                Application.DoEvents();

                e.Handled = true;
                ((ReportViewer)sender).RefreshReport();
            }
        }

        private void frmPrintView_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (SysVar.MDIParentForm!=null)
                SysVar.MDIParentForm.BringToFront();
        }
        private decimal GetMargin(string strRpt, string strMargin)
        {
            try
            {
                string strvalue = BaseFunctions.GetMatch(strRpt, string.Format("<{0}>(?<value>.*?)in</{0}>", strMargin));

                if (strvalue.Length == 0)
                {
                    return 0;
                }

                return decimal.Parse(strvalue);
            }
            catch
            {
                return 0;
            }
        }

        ////public void Dispose()
        ////{
        ////    if (m_streams != null)
        ////    {
        ////        foreach (Stream stream in m_streams)
        ////            stream.Close();
        ////        m_streams = null;
        ////    }
        ////}

    }
}